home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / tcp_ip / wnos / wn941101 / socket.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-10  |  45.2 KB  |  1,982 lines

  1. #include <stdio.h>
  2. #ifdef    __STDC__
  3. #include <stdarg.h>
  4. #endif
  5. #include "global.h"
  6. #include "config.h"
  7. #include "mbuf.h"
  8. #include "netuser.h"
  9. #include "timer.h"
  10. #include "iface.h"
  11. #include "ip.h"
  12. #include "tcp.h"
  13. #include "udp.h"
  14. #include "ax25.h"
  15. #include "netrom.h"
  16. #include "nr4.h"
  17. #include "proc.h"
  18. #ifdef LZW
  19. #include "lzw.h"
  20. #endif
  21. #include "usock.h"
  22. #include "socket.h"
  23.  
  24. static void near autobind __ARGS((int s,int af));
  25. static int near checkaddr __ARGS((int type,char *name,int namelen));
  26. static void rip_recv __ARGS((struct raw_ip *rp));
  27. static void s_trcall __ARGS((struct tcb *tcb,int cnt));
  28. static void s_tscall __ARGS((struct tcb *tcb,int old,int new));
  29. static void s_ttcall __ARGS((struct tcb *tcb,int cnt));
  30. static void s_urcall __ARGS((struct iface *iface,struct udp_cb *udp,int cnt));
  31. static void trdiscard __ARGS((struct tcb *tcb,int cnt));
  32. #ifdef    NETROM
  33. static void s_nrcall __ARGS((struct nr4cb *cb,int cnt));
  34. static void s_nscall __ARGS((struct nr4cb *cb,int old,int new));
  35. static void s_ntcall __ARGS((struct nr4cb *cb,int cnt));
  36. #endif
  37.  
  38. static int16 Lport = 1024;
  39.  
  40. char *Socktypes[] = {
  41.     "Not Used",
  42.     "TCP",
  43.     "UDP",
  44.     "AX25 I",
  45.     "AX25 UI",
  46.     "Raw IP",
  47.     "NETROM3",
  48.     "NETROM",
  49.     "Loc St",
  50.     "Loc Dg"
  51. };
  52.  
  53. char Badsocket[] = "Bad socket";
  54. char Nosocket[] = "Can't create socket\n";
  55.  
  56. struct usock *Usock = NULLUSOCK;        /* Socket entry array */
  57. int Nusock = DEFNSOCK;                    /* Number of socket entries */
  58.  
  59. /* The following two variables are needed because there can be only one
  60.  * socket listening on each of the AX.25 modes (I and UI)
  61.  */
  62.  /* definition !! */
  63. int Axi_sock = -1;    /* Socket number listening for AX25 connections */
  64. #ifdef AX25
  65. static int Axui_sock = -1;    /* Socket number listening for AX25 UI frames */
  66. #endif /* AX25 */
  67.  
  68. /* Initialize user socket array */
  69. void
  70. sockinit()
  71. {
  72.     if(Usock != NULLUSOCK)
  73.         return;    /* Already initialized */
  74.     Usock = (struct usock *)cxallocw(Nusock,sizeof(struct usock));
  75. }
  76.  
  77. /* Create a user socket, return socket index
  78.  * The mapping to actual protocols is as follows:
  79.  *
  80.  *
  81.  * ADDRESS FAMILY    Stream        Datagram    Raw        Seq. Packet
  82.  *
  83.  * AF_INET            TCP            UDP            IP
  84.  * AF_AX25            I-frames    UI-frames
  85.  * AF_NETROM        NET/ROM L3  NET/ROM L4
  86.  * AF_LOCAL            stream loopback    packet loopback
  87.  */
  88. int
  89. socket(af,type,protocol)
  90. int af;            /* Address family */
  91. int type;        /* Stream or datagram */
  92. int protocol;    /* Used for raw IP sockets */
  93. {
  94.     struct usock *up;
  95.     int s;
  96.  
  97.     for(up = Usock; up < &Usock[Nusock]; up++)
  98.         if(up->type == NOTUSED)
  99.             break;
  100.  
  101.     if(up == &Usock[Nusock]) {
  102.         /* None left */
  103.         errno = EMFILE;
  104.         return -1;
  105.     }
  106.  
  107.     up->refcnt = 1;
  108.     s = (int)(up - Usock + SOCKBASE);
  109.     errno = 0;
  110.     up->noblock = 0;
  111.     up->rdysock = -1;
  112.     up->cb.p = NULLCHAR;
  113.     up->peername = up->name = NULLCHAR;
  114.     up->namelen = up->peernamelen = 0;
  115.     up->owner = Curproc;
  116.     up->obuf = NULLBUF;
  117.     memset(up->errcodes,0,sizeof(up->errcodes));
  118.     memset(up->eol,0,sizeof(up->eol));
  119.     up->flush = '\n';    /* default is line buffered */
  120.     switch(af){
  121.     case AF_LOCAL:
  122.         up->cb.local = (struct loc *)mxallocw(sizeof(struct loc));
  123.         up->cb.local->peer = up;
  124.         switch(type){
  125.         case SOCK_STREAM:
  126.             up->type = TYPE_LOCAL_STREAM;
  127.             up->cb.local->hiwat = LOCSFLOW;
  128.             break;
  129.         case SOCK_DGRAM:
  130.             up->type = TYPE_LOCAL_DGRAM;
  131.             up->cb.local->hiwat = LOCDFLOW;
  132.             break;
  133.         default:
  134.             xfree(up->cb.local);
  135.             errno = ESOCKTNOSUPPORT;
  136.             break;
  137.         }
  138.         break;
  139. #ifdef    AX25
  140.     case AF_AX25:
  141.         switch(type){
  142.         case SOCK_STREAM:
  143.             up->type = TYPE_AX25I;
  144.             break;
  145.         case SOCK_DGRAM:
  146.             up->type = TYPE_AX25UI;
  147.             break;
  148.         default:
  149.             errno = ESOCKTNOSUPPORT;
  150.             break;
  151.         }
  152.         strcpy(up->eol,AX_EOL);
  153.         break;
  154. #endif
  155. #ifdef NETROM
  156.     case AF_NETROM:
  157.         switch(type){
  158.         case SOCK_RAW:
  159.             up->type = TYPE_NETROML3;
  160.             up->cb.rnr = raw_nr((char)protocol);
  161.             break;
  162.         case SOCK_SEQPACKET:
  163.             up->type = TYPE_NETROML4;
  164.             break;
  165.         default:
  166.             errno = ESOCKTNOSUPPORT;
  167.             break;
  168.         }
  169.         strcpy(up->eol,AX_EOL);
  170.         break;
  171. #endif
  172.     case AF_INET:
  173.         switch(type){
  174.         case SOCK_STREAM:
  175.             up->type = TYPE_TCP;
  176.             strcpy(up->eol,INET_EOL);
  177.             break;
  178.         case SOCK_DGRAM:
  179.             up->type = TYPE_UDP;
  180.             break;
  181.         case SOCK_RAW:
  182.             up->type = TYPE_RAW;
  183.             up->cb.rip = raw_ip(protocol,rip_recv);
  184.             up->cb.rip->user = s;
  185.             break;
  186.         default:
  187.             errno = ESOCKTNOSUPPORT;
  188.             break;
  189.         }
  190.         break;
  191.     default:
  192.         errno = EAFNOSUPPORT;
  193.         break;
  194.     }
  195.     if(errno)
  196.         return -1;
  197.  
  198.     return s;
  199. }
  200.  
  201. /* Attach a local address/port to a socket. If not issued before a connect
  202.  * or listen, will be issued automatically
  203.  */
  204. int
  205. bind(s,name,namelen)
  206. int s;        /* Socket index */
  207. char *name;    /* Local name */
  208. int namelen;    /* Length of name */
  209. {
  210.     struct usock *up;
  211.     union sp local;
  212.     struct socket lsock;
  213.  
  214.     if((up = itop(s)) == NULLUSOCK){
  215.         errno = EBADF;
  216.         return -1;
  217.     }
  218.     if(up->type == TYPE_LOCAL_STREAM || up->type == TYPE_LOCAL_DGRAM){
  219.         errno = EINVAL;
  220.         return -1;
  221.     }
  222.     if(name == NULLCHAR){
  223.         errno = EFAULT;
  224.         return -1;
  225.     }
  226.     if(up->name != NULLCHAR){
  227.         /* Bind has already been issued */
  228.         errno = EINVAL;
  229.         return -1;
  230.     }
  231.     if(checkaddr(up->type,name,namelen) == -1){
  232.         /* Incorrect length or family for chosen protocol */
  233.         errno = EAFNOSUPP;
  234.         return -1;
  235.     }
  236.     /* Stash name in an allocated block */
  237.     up->name = mxallocw(namelen);
  238.     memcpy(up->name,name,namelen);
  239.     up->namelen = namelen;
  240.     /* Create control block for datagram sockets */
  241.     switch(up->type){
  242.     case TYPE_UDP:
  243.         local.in = (struct sockaddr_in *)up->name;
  244.         lsock.address = local.in->sin_addr.s_addr;
  245.         lsock.port = local.in->sin_port;
  246.         up->cb.udp = open_udp(&lsock,s_urcall);
  247.         up->cb.udp->user = s;
  248.         break;
  249. #ifdef    AX25
  250.     case TYPE_AX25UI:
  251.         if(Axui_sock != -1){
  252.             errno = EADDRINUSE;
  253.             return -1;
  254.         }
  255.         Axui_sock = s;
  256.         break;
  257. #endif
  258.     }
  259.     return 0;
  260. }
  261. /* Post a listen on a socket */
  262. int
  263. listen(s,backlog)
  264. int s;        /* Socket index */
  265. int backlog;    /* 0 for a single connection, 1 for multiple connections */
  266. {
  267.     struct usock *up;
  268.     union sp local;
  269.     struct socket lsock;
  270.  
  271.     if((up = itop(s)) == NULLUSOCK){
  272.         errno = EBADF;
  273.         return -1;
  274.     }
  275.     if(up->type == TYPE_LOCAL_STREAM || up->type == TYPE_LOCAL_DGRAM){
  276.         errno = EINVAL;
  277.         return -1;
  278.     }
  279.     if(up->cb.p != NULLCHAR){
  280.         errno = EISCONN;
  281.         return -1;
  282.     }
  283.     switch(up->type){
  284.     case TYPE_TCP:
  285.         if(up->name == NULLCHAR)
  286.             autobind(s,AF_INET);
  287.  
  288.         local.in = (struct sockaddr_in *)up->name;
  289.         lsock.address = local.in->sin_addr.s_addr;
  290.         lsock.port = local.in->sin_port;
  291.         up->cb.tcb = open_tcp(
  292.             &lsock,
  293.             NULLSOCK,
  294.             backlog ? TCP_SERVER : TCP_PASSIVE,
  295.             0,
  296.             s_trcall,
  297.             s_ttcall,
  298.             s_tscall,
  299.             0,
  300.             s);
  301.         break;
  302. #ifdef AX25
  303.     case TYPE_AX25I:
  304.         if(up->name == NULLCHAR)
  305.             autobind(s,AF_AX25);
  306.         if(s != Axi_sock){
  307.             errno = EOPNOTSUPP;
  308.             return -1;
  309.         }
  310.         local.ax = (struct sockaddr_ax *)up->name;
  311.         up->cb.ax25 = open_ax25(
  312.             NULLIF,
  313.             local.ax->ax25_addr,
  314.             NULLCHAR,
  315.             backlog ? AX_SERVER : AX_PASSIVE,
  316.             s_arcall,
  317.             s_atcall,
  318.             s_ascall,
  319.             s);
  320.         break;
  321. #endif
  322. #ifdef NETROM
  323.     case TYPE_NETROML4:
  324.         if(up->name == NULLCHAR)
  325.             autobind(s,AF_NETROM);
  326.         local.nr = (struct sockaddr_nr *)up->name;
  327.         up->cb.nr4 = open_nr4(
  328.             &local.nr->nr_addr,
  329.             NULLNRADDR,
  330.             backlog ? AX_SERVER : AX_PASSIVE,
  331.             s_nrcall,
  332.             s_ntcall,
  333.             s_nscall,
  334.             s);
  335.         break;
  336. #endif
  337.     default:
  338.         /* Listen not supported on datagram sockets */
  339.         errno = EOPNOTSUPP;
  340.         return -1;        
  341.     }
  342.     return 0;
  343. }
  344. /* Initiate active open. For datagram sockets, merely bind the remote address. */
  345. int
  346. connect(s,peername,peernamelen)
  347. int s;            /* Socket index */
  348. char *peername;        /* Peer name */
  349. int peernamelen;    /* Length of peer name */
  350. {
  351.     struct usock *up;
  352.     union cb cb;
  353.     union sp local,remote;
  354.     struct socket lsock,fsock;
  355. #ifdef    AX25
  356.     struct iface *iface;
  357. #endif
  358.     if((up = itop(s)) == NULLUSOCK){
  359.         errno = EBADF;
  360.         return -1;
  361.     }
  362.     if(up->type == TYPE_LOCAL_DGRAM || up->type == TYPE_LOCAL_STREAM){
  363.         errno = EINVAL;
  364.         return -1;
  365.     }
  366.     if(peername == NULLCHAR){
  367.         /* Connect must specify a remote address */
  368.         errno = EFAULT;
  369.         return -1;
  370.     }
  371.     if(checkaddr(up->type,peername,peernamelen) == -1){
  372.         errno = EAFNOSUPPORT;
  373.         return -1;
  374.     }
  375.     /* Raw socket control blocks are created in socket() */
  376.     if(up->type != TYPE_RAW && up->type != TYPE_NETROML3 &&
  377.        up->cb.p != NULLCHAR){
  378.         errno = EISCONN;
  379.         return -1;
  380.     }
  381.     up->peername = mxallocw(peernamelen);
  382.     memcpy(up->peername,peername,peernamelen);
  383.     up->peernamelen = peernamelen;
  384.     /* Set up the local socket structures */
  385.     if(up->name == NULLCHAR){
  386.         switch(up->type){
  387.         case TYPE_TCP:
  388.         case TYPE_UDP:
  389.         case TYPE_RAW:
  390.             autobind(s,AF_INET);
  391.             break;
  392. #ifdef    AX25
  393.         case TYPE_AX25I:
  394.         case TYPE_AX25UI:
  395.             autobind(s,AF_AX25);
  396.             break;
  397. #endif
  398. #ifdef    NETROM
  399.         case TYPE_NETROML3:
  400.         case TYPE_NETROML4:
  401.             autobind(s,AF_NETROM);
  402.             break;
  403. #endif
  404.         }
  405.     }
  406.     switch(up->type){
  407.     case TYPE_TCP:
  408.         /* Construct the TCP-style ports from the sockaddr structs */
  409.         local.in = (struct sockaddr_in *)up->name;
  410.         remote.in = (struct sockaddr_in *)up->peername;
  411.  
  412.         if(local.in->sin_addr.s_addr == INADDR_ANY)
  413.             /* Choose a local address */
  414.             local.in->sin_addr.s_addr =
  415.              locaddr(remote.in->sin_addr.s_addr);
  416.  
  417.         lsock.address = local.in->sin_addr.s_addr;
  418.         lsock.port = local.in->sin_port;
  419.         fsock.address = remote.in->sin_addr.s_addr;
  420.         fsock.port = remote.in->sin_port;
  421.  
  422.         /* Open the TCB in active mode */
  423.         up->cb.tcb = open_tcp(&lsock,&fsock,TCP_ACTIVE,0,
  424.          s_trcall,s_ttcall,s_tscall,0,s);
  425.  
  426.         /* Wait for the connection to complete */
  427.         while((cb.tcb = up->cb.tcb) != NULLTCB && cb.tcb->state != TCP_ESTABLISHED){
  428.             if(up->noblock){
  429.                 errno = EWOULDBLOCK;
  430.                 return -1;
  431.             } else if((errno = (int)pwait(up)) != 0){
  432.                 return -1;
  433.             }
  434.         }
  435.         if(cb.tcb == NULLTCB){
  436.             /* Probably got refused */
  437.             xfree(up->peername);
  438.             up->peername = NULLCHAR;
  439.             errno = ECONNREFUSED;
  440.             return -1;
  441.         }
  442.         break;
  443.     case TYPE_UDP:
  444. #ifdef    AX25
  445.     case TYPE_AX25UI:
  446. #endif
  447. #ifdef    NETROM
  448.     case TYPE_NETROML3:
  449. #endif
  450.     case TYPE_RAW:
  451.         /* Control block already created by bind() */
  452.         break;
  453. #ifdef    AX25
  454.     case TYPE_AX25I:
  455.         local.ax = (struct sockaddr_ax *)up->name;
  456.         remote.ax = (struct sockaddr_ax *)up->peername;
  457.         if((iface = if_lookup(remote.ax->iface)) == NULLIF){
  458.             errno = EINVAL;
  459.             return -1;
  460.         }
  461.         if(local.ax->ax25_addr[0] == '\0'){
  462.             /* The local address was unspecified; set it from
  463.              * the interface address
  464.              */
  465.             memcpy(local.ax->ax25_addr,iface->hwaddr,AXALEN);
  466.         }
  467.         /* If we already have an AX25 link we can use it */
  468.         if((up->cb.ax25 = find_ax25(local.ax->ax25_addr,remote.ax->ax25_addr)) != NULLAX25
  469.            && up->cb.ax25->state != DISCONNECTED &&
  470.            up->cb.ax25->user == -1) {
  471.             up->cb.ax25->user = s;
  472.             up->cb.ax25->r_upcall = s_arcall;
  473.             up->cb.ax25->t_upcall = s_atcall;
  474.             up->cb.ax25->s_upcall = s_ascall;
  475.             if(up->cb.ax25->state == CONNECTED)
  476.                 return 0;
  477.         } else {
  478.             up->cb.ax25 = open_ax25(
  479.                 iface,
  480.                 local.ax->ax25_addr,
  481.                 remote.ax->ax25_addr,
  482.                 AX_ACTIVE,
  483.                 s_arcall,
  484.                 s_atcall,
  485.                 s_ascall,
  486.                 s);
  487.         }
  488.  
  489.         /* Wait for the connection to complete */
  490.         while((cb.ax25 = up->cb.ax25) != NULLAX25 && cb.ax25->state != CONNECTED){
  491.             if(up->noblock){
  492.                 errno = EWOULDBLOCK;
  493.                 return -1;
  494.             } else if((errno = (int)pwait(up)) != 0){
  495.                 return -1;
  496.             }
  497.         }
  498.         if(cb.ax25 == NULLAX25){
  499.             /* Connection probably already exists */
  500.             xfree(up->peername);
  501.             up->peername = NULLCHAR;
  502.             errno = ECONNREFUSED;
  503.             return -1;
  504.         }
  505.         break;
  506. #endif
  507. #ifdef    NETROM
  508.     case TYPE_NETROML4:
  509.         local.nr = (struct sockaddr_nr *)up->name;
  510.         remote.nr = (struct sockaddr_nr *)up->peername;
  511.         up->cb.nr4 = open_nr4(&local.nr->nr_addr,&remote.nr->nr_addr,
  512.           AX_ACTIVE,s_nrcall,s_ntcall,s_nscall,s);
  513.  
  514.         /* Wait for the connection to complete */
  515.         while((cb.nr4 = up->cb.nr4) != NULLNR4CB && cb.nr4->state != NR4STCON){
  516.             if(up->noblock){
  517.                 errno = EWOULDBLOCK;
  518.                 return -1;
  519.             } else if((errno = (int)pwait(up)) != 0){
  520.                 return -1;
  521.             }
  522.         }
  523.         if(cb.nr4 == NULLNR4CB){
  524.             /* Connection probably already exists */
  525.             xfree(up->peername);
  526.             up->peername = NULLCHAR;
  527.             errno = ECONNREFUSED;
  528.             return -1;
  529.         }
  530.         break;
  531. #endif
  532.     }
  533.     return 0;
  534. }
  535. /* Wait for a connection. Valid only for connection-oriented sockets. */
  536. int
  537. accept(s,peername,peernamelen)
  538. int s;            /* Socket index */
  539. char *peername;        /* Peer name */
  540. int *peernamelen;    /* Length of peer name */
  541. {
  542.     int i;
  543.     struct usock *up;
  544.  
  545.     if((up = itop(s)) == NULLUSOCK){
  546.         errno = EBADF;
  547.         return -1;
  548.     }
  549.     if(up->type == TYPE_LOCAL_DGRAM || up->type == TYPE_LOCAL_STREAM){
  550.         errno = EINVAL;
  551.         return -1;
  552.     }
  553.     if(up->cb.p == NULLCHAR){
  554.         errno = EOPNOTSUPP;
  555.         return -1;
  556.     }
  557.     /* Accept is valid only for stream sockets */
  558.     switch(up->type){
  559.     case TYPE_TCP:
  560. #ifdef    AX25
  561.     case TYPE_AX25I:
  562. #endif
  563. #ifdef    NETROM
  564.     case TYPE_NETROML4:
  565. #endif
  566.         break;
  567.     default:
  568.         errno = EOPNOTSUPP;
  569.         return -1;
  570.     }    
  571.     /* Wait for the state-change upcall routine to signal us */
  572.     while(up->cb.p != NULLCHAR && up->rdysock == -1){
  573.         if(up->noblock){
  574.             errno = EWOULDBLOCK;
  575.             return -1;
  576.         } else if((errno = (int)pwait(up)) != 0){
  577.             return -1;
  578.         }
  579.     }
  580.     if(up->cb.p == NULLCHAR){
  581.         /* Blown away */
  582.         errno = EBADF;
  583.         return -1;
  584.     }
  585.     i = up->rdysock;
  586.     up->rdysock = -1;
  587.  
  588.     up = itop(i);
  589.     if(peername != NULLCHAR && peernamelen != NULL){
  590.         *peernamelen = (int)min(up->peernamelen,*peernamelen);
  591.         memcpy(peername,up->peername,*peernamelen);
  592.     }
  593.     return i;
  594. }
  595.  
  596. /* Low-level receive routine. Passes mbuf back to user; more efficient than
  597.  * higher-level functions recv() and recvfrom(). Datagram sockets ignore
  598.  * the len parameter.
  599.  */
  600. int
  601. recv_mbuf(s,bpp,flags,from,fromlen)
  602. int s;                    /* Socket index */
  603. struct mbuf **bpp;        /* Place to stash receive buffer */
  604. int flags;                /* Unused; will control out-of-band data, etc */
  605. char *from;                /* Peer address (only for datagrams) */
  606. int *fromlen;            /* Length of peer address */
  607. {
  608.     struct usock *up;
  609.     int cnt = -1;
  610.     union cb cb;
  611.     struct socket fsocket;
  612. #ifdef    NETROM
  613.     struct nr3hdr n3hdr;
  614. #endif
  615.     union sp remote;
  616.     struct ip ip;
  617.     struct mbuf *bp;
  618.  
  619.     if((up = itop(s)) == NULLUSOCK){
  620.         errno = EBADF;
  621.         return -1;
  622.     }
  623.     if(up->ibuf != NULLBUF){
  624.         /* Return input buffer */
  625.         cnt = len_p(up->ibuf);
  626.         if(bpp != NULLBUFP)
  627.             *bpp = up->ibuf;
  628.         else
  629.             free_p(up->ibuf);
  630.         up->ibuf = NULLBUF;
  631.         return cnt;
  632.     }
  633.     switch(up->type){
  634.     case TYPE_LOCAL_STREAM:
  635.     case TYPE_LOCAL_DGRAM:
  636.         while(up->cb.local != NULLLOC && up->cb.local->q == NULLBUF
  637.           && up->cb.local->peer != NULLUSOCK) {
  638.             if(up->noblock){
  639.                 errno = EWOULDBLOCK;
  640.                 return -1;
  641.             } else if((errno = (int)pwait(up)) != 0){
  642.                 return -1;
  643.             }
  644.         }
  645.         if(up->cb.local == NULLLOC){
  646.             errno = EBADF;
  647.             return -1;
  648.         }
  649.         if(up->cb.local->q == NULLBUF &&
  650.            up->cb.local->peer == NULLUSOCK){
  651.             errno = ENOTCONN;
  652.             return -1;
  653.         }
  654.         /* For datagram sockets, this will return the
  655.          * first packet on the queue. For stream sockets,
  656.          * this will return everything.
  657.          */
  658.         bp = dequeue(&up->cb.local->q);
  659.         if(up->cb.local->q == NULLBUF
  660.          && (up->cb.local->flags & LOC_SHUTDOWN))
  661.             close_s(s);
  662.         psignal(up,0);
  663.         cnt = len_p(bp);
  664.         break;
  665.     case TYPE_TCP:
  666.         while((cb.tcb = up->cb.tcb) != NULLTCB
  667.           && cb.tcb->r_upcall != trdiscard
  668.           && (cnt = recv_tcp(cb.tcb,&bp,(int16)0)) == -1){
  669.             if(up->noblock){
  670.                 errno = EWOULDBLOCK;
  671.                 return -1;
  672.             } else if((errno = (int)pwait(up)) != 0){
  673.                 return -1;
  674.             }
  675.         }
  676.         if(cb.tcb == NULLTCB){
  677.             /* Connection went away */
  678.             errno = ENOTCONN;
  679.             return -1;
  680.         } else if(cb.tcb->r_upcall == trdiscard){
  681.             /* Receive shutdown has been done */
  682.             errno = ENOTCONN;    /* CHANGE */
  683.             return -1;
  684.         }
  685.         break;
  686.     case TYPE_UDP:
  687.         while((cb.udp = up->cb.udp) != NULLUDP
  688.           && (cnt = recv_udp(cb.udp,&fsocket,&bp)) == -1){
  689.             if(up->noblock){
  690.                 errno = EWOULDBLOCK;
  691.                 return -1;
  692.             } else if((errno = (int)pwait(up)) != 0){
  693.                 return -1;
  694.             }
  695.         }
  696.         if(cb.udp == NULLUDP){
  697.             /* Connection went away */
  698.             errno = ENOTCONN;
  699.             return -1;
  700.         }
  701.         if(from != NULLCHAR && fromlen != (int *)NULL && *fromlen >= SOCKSIZE){
  702.             remote.in = (struct sockaddr_in *)from;
  703.             remote.in->sin_family = AF_INET;
  704.             remote.in->sin_addr.s_addr = fsocket.address;
  705.             remote.in->sin_port = fsocket.port;
  706.             *fromlen = SOCKSIZE;
  707.         }
  708.         break;
  709.     case TYPE_RAW:
  710.         while((cb.rip = up->cb.rip) != NULLRIP
  711.          && cb.rip->rcvq == NULLBUF){
  712.             if(up->noblock){
  713.                 errno = EWOULDBLOCK;
  714.                 return -1;
  715.             } else if((errno = (int)pwait(up)) != 0){
  716.                 return -1;
  717.             }
  718.         }
  719.         if(cb.rip == NULLRIP){
  720.             /* Connection went away */
  721.             errno = ENOTCONN;
  722.             return -1;
  723.         }
  724.         bp = dequeue(&cb.rip->rcvq);
  725.         ntohip(&ip,&bp);
  726.  
  727.         cnt = len_p(bp);
  728.         if(from != NULLCHAR && fromlen != (int *)NULL && *fromlen >= SOCKSIZE){
  729.             remote.in = (struct sockaddr_in *)from;
  730.             remote.in->sin_family = AF_INET;
  731.             remote.in->sin_addr.s_addr = ip.source;
  732.             remote.in->sin_port = 0;
  733.             *fromlen = SOCKSIZE;
  734.         }
  735.         break;
  736. #ifdef    AX25
  737.     case TYPE_AX25I:
  738.         while((cb.ax25 = up->cb.ax25) != NULLAX25
  739.          && (bp = recv_ax25(cb.ax25,(int16)0)) == NULLBUF){
  740.             if(up->noblock){
  741.                 errno = EWOULDBLOCK;
  742.                 return -1;
  743.             } else if((errno = (int)pwait(up)) != 0){
  744.                 return -1;
  745.             }
  746.         }
  747.         if(cb.ax25 == NULLAX25){
  748.             /* Connection went away */
  749.             errno = ENOTCONN;
  750.             return -1;
  751.         }
  752.         cnt = bp->cnt;
  753.         break;
  754.     case TYPE_AX25UI:
  755.         while(s == Axui_sock) {
  756.             if(up->noblock){
  757.                 errno = EWOULDBLOCK;
  758.                 return -1;
  759.             }
  760.         }
  761.         if(s != Axui_sock){
  762.             errno = ENOTCONN;
  763.             return -1;
  764.         }
  765.         bp = NULLBUF;
  766.  
  767.         if(from != NULLCHAR && fromlen != NULLINT
  768.            && *fromlen >= sizeof(struct sockaddr_ax)){
  769.             pullup(&bp,from,sizeof(struct sockaddr_ax));
  770.             *fromlen = sizeof(struct sockaddr_ax);
  771.         } else {
  772.             pullup(&bp,NULLCHAR,sizeof(struct sockaddr_ax));
  773.         }
  774.         cnt = len_p(bp);
  775.         break;
  776. #endif
  777. #ifdef NETROM
  778.     case TYPE_NETROML3:
  779.         while((cb.rnr = up->cb.rnr) != NULLRNR
  780.          && cb.rnr->rcvq == NULLBUF){
  781.             if(up->noblock){
  782.                 errno = EWOULDBLOCK;
  783.                 return -1;
  784.             } else if((errno = (int)pwait(up)) != 0){
  785.                 return -1;
  786.             }
  787.         }
  788.         if(cb.rnr == NULLRNR){
  789.             /* Connection went away */
  790.             errno = ENOTCONN;
  791.             return -1;
  792.         }
  793.         bp = dequeue(&cb.rnr->rcvq);
  794.         ntohnr3(&n3hdr,&bp);
  795.         cnt = len_p(bp);
  796.         if(from != NULLCHAR && fromlen != NULLINT
  797.            && *fromlen >= sizeof(struct sockaddr_nr)){
  798.             remote.nr = (struct sockaddr_nr *)from;
  799.             remote.nr->nr_family = AF_NETROM;
  800.             /* The callsign of the local user is not part of
  801.                NET/ROM level 3, so that field is not used here */
  802.             memcpy(remote.nr->nr_addr.node,n3hdr.source,AXALEN);
  803.             *fromlen = sizeof(struct sockaddr_nr);
  804.         }
  805.         break;
  806.     case TYPE_NETROML4:
  807.         while((cb.nr4 = up->cb.nr4) != NULLNR4CB
  808.          && (bp = recv_nr4(cb.nr4,(int16)0)) == NULLBUF){
  809.             if(up->noblock){
  810.                 errno = EWOULDBLOCK;
  811.                 return -1;
  812.             } else if((errno = (int)pwait(up)) != 0){
  813.                 return -1;
  814.             }
  815.         }
  816.         if(cb.nr4 == NULLNR4CB){
  817.             /* Connection went away */
  818.             errno = ENOTCONN;
  819.             return -1;
  820.         }
  821.         cnt = bp->cnt;
  822.         break;
  823. #endif
  824.     }
  825.     if(bpp != NULLBUFP)
  826.         *bpp = bp;
  827.     else
  828.         free_p(bp);
  829.     return cnt;
  830. }
  831.  
  832. /* Low level send routine; user supplies mbuf for transmission. More
  833.  * efficient than send() or sendto(), the higher level interfaces.
  834.  * The "to" and "tolen" parameters are ignored on connection-oriented
  835.  * sockets.
  836.  *
  837.  * In case of error, bp is freed so the caller doesn't have to worry about it.
  838.  */
  839. int
  840. send_mbuf(s,bp,flags,to,tolen)
  841. int s;                    /* Socket index */
  842. struct mbuf *bp;        /* Buffer to send */
  843. int flags;                /* not currently used */
  844. char *to;                /* Destination, only for datagrams */
  845. int tolen;                /* Length of destination */
  846. {
  847.     struct usock *up;
  848.     union cb cb;
  849.     union sp local,remote;
  850.     struct socket lsock,fsock;
  851.     int cnt;
  852.  
  853.     if((up = itop(s)) == NULLUSOCK){
  854.         free_p(bp);
  855.         errno = EBADF;
  856.         return -1;
  857.     }
  858. #ifndef    XXX
  859.     if(up->obuf != NULLBUF){
  860.         /* If there's unflushed output, send it.
  861.          * Note the importance of clearing up->obuf
  862.          * before the recursive call!
  863.          */
  864.         struct mbuf *bp1;
  865.  
  866.         bp1 = up->obuf;
  867.         up->obuf = NULLBUF;
  868.         send_mbuf(s,bp1,flags,to,tolen);
  869.     }
  870. #endif
  871.     if(up->name == NULLCHAR){
  872.         /* Automatic local name assignment for datagram sockets */
  873.         switch(up->type){
  874.         case TYPE_LOCAL_STREAM:
  875.         case TYPE_LOCAL_DGRAM:
  876.             break;    /* no op */
  877.         case TYPE_UDP:
  878.         case TYPE_RAW:
  879.             autobind(s,AF_INET);
  880.             break;
  881. #ifdef    AX25
  882.         case TYPE_AX25UI:
  883.             autobind(s,AF_AX25);
  884.             break;
  885. #endif
  886. #ifdef    NETROM
  887.         case TYPE_NETROML3:
  888.         case TYPE_NETROML4:
  889.             autobind(s,AF_NETROM);
  890.             break;
  891. #endif
  892.         default:
  893.             free_p(bp);
  894.             errno = ENOTCONN;
  895.             return -1;
  896.         }
  897.     }
  898.     cnt = len_p(bp);
  899.     switch(up->type){
  900.     case TYPE_LOCAL_DGRAM:
  901.         if(up->cb.local->peer == NULLUSOCK){
  902.             free_p(bp);
  903.             errno = ENOTCONN;
  904.             return -1;
  905.         }
  906.         enqueue(&up->cb.local->peer->cb.local->q,bp);
  907.         psignal(up->cb.local->peer,0);
  908.         /* If high water mark has been reached, block */
  909.         while(len_q(up->cb.local->q) >= up->cb.local->hiwat){
  910.             if(up->noblock){
  911.                 errno = EWOULDBLOCK;
  912.                 return -1;
  913.             } else if((errno = (int)pwait(up->cb.local->peer)) != 0){
  914.                 return -1;
  915.             }
  916.         }
  917.         if(up->cb.local->peer == NULLUSOCK){
  918.             errno = ENOTCONN;
  919.             return -1;
  920.         }
  921.         break;
  922.     case TYPE_LOCAL_STREAM:
  923.         if(up->cb.local->peer == NULLUSOCK){
  924.             free_p(bp);
  925.             errno = ENOTCONN;
  926.             return -1;
  927.         }
  928.         append(&up->cb.local->peer->cb.local->q,bp);
  929.         psignal(up->cb.local->peer,0);
  930.         /* If high water mark has been reached, block */
  931.         while(up->cb.local->peer != NULLUSOCK &&
  932.               len_p(up->cb.local->peer->cb.local->q) >=
  933.               up->cb.local->peer->cb.local->hiwat){
  934.             if(up->noblock){
  935.                 errno = EWOULDBLOCK;
  936.                 return -1;
  937.             } else if((errno = (int)pwait(up->cb.local->peer)) != 0){
  938.                 return -1;
  939.             }
  940.         }
  941.         if(up->cb.local->peer == NULLUSOCK){
  942.             errno = ENOTCONN;
  943.             return -1;
  944.         }
  945.         break;
  946.     case TYPE_TCP:
  947.         if((cb.tcb = up->cb.tcb) == NULLTCB){
  948.             free_p(bp);
  949.             errno = ENOTCONN;
  950.             return -1;
  951.         }
  952.         cnt = send_tcp(cb.tcb,bp);
  953.  
  954.         while((cb.tcb = up->cb.tcb) != NULLTCB &&
  955.          cb.tcb->sndcnt > cb.tcb->window){
  956.             /* Send queue is full */
  957.             if(up->noblock){
  958.                 errno = EWOULDBLOCK;
  959.                 return -1;
  960.             } else if((errno = (int)pwait(up)) != 0){
  961.                 return -1;
  962.             }
  963.         }
  964.          if(cb.tcb == NULLTCB){
  965.             errno = ENOTCONN;
  966.             return -1;
  967.         }
  968.         break;
  969.     case TYPE_UDP:
  970.         local.in = (struct sockaddr_in *)up->name;
  971.         lsock.address = local.in->sin_addr.s_addr;
  972.         lsock.port = local.in->sin_port;
  973.         if(to != NULLCHAR)
  974.             remote.in = (struct sockaddr_in *)to;
  975.         else if(up->peername != NULLCHAR)
  976.             remote.in = (struct sockaddr_in *)up->peername;
  977.         else {
  978.             errno = ENOTCONN;
  979.             return -1;
  980.         }
  981.         fsock.address = remote.in->sin_addr.s_addr;
  982.         fsock.port = remote.in->sin_port;
  983.         send_udp(&lsock,&fsock,0,0,bp,0,0,0);
  984.         break;
  985.     case TYPE_RAW:
  986.         local.in = (struct sockaddr_in *)up->name;
  987.         if(to != NULLCHAR)
  988.             remote.in = (struct sockaddr_in *)to;
  989.         else if(up->peername != NULLCHAR)
  990.             remote.in = (struct sockaddr_in *)up->peername;
  991.         else {
  992.             errno = ENOTCONN;
  993.             return -1;
  994.         }
  995.         ip_send(local.in->sin_addr.s_addr,remote.in->sin_addr.s_addr,
  996.             (char)up->cb.rip->protocol,0,0,bp,0,0,0);
  997.         break;
  998. #ifdef    AX25
  999.     case TYPE_AX25I:
  1000.         if((cb.ax25 = up->cb.ax25) == NULLAX25){
  1001.             free_p(bp);
  1002.             errno = ENOTCONN;
  1003.             return -1;
  1004.         }
  1005.         send_ax25(cb.ax25,bp,STREAM);
  1006.  
  1007.         while((cb.ax25 = up->cb.ax25) != NULLAX25 &&
  1008.          len_p(cb.ax25->txq) > Axwindow){
  1009.             if(up->noblock){
  1010.                 errno = EWOULDBLOCK;
  1011.                 return -1;
  1012.             } else if((errno = (int)pwait(up)) != 0){
  1013.                 errno = EINTR;
  1014.                 return -1;
  1015.             }
  1016.         }
  1017.         if(cb.ax25 == NULLAX25){
  1018.             errno = EBADF;
  1019.             return -1;
  1020.         }
  1021.         break;
  1022.     case TYPE_AX25UI:
  1023.         local.ax = (struct sockaddr_ax *)up->name;
  1024.         if(to != NULLCHAR)
  1025.             remote.ax = (struct sockaddr_ax *)to;
  1026.         else if(up->peername != NULLCHAR)
  1027.             remote.ax = (struct sockaddr_ax *)up->peername;
  1028.         else {
  1029.             errno = ENOTCONN;
  1030.             return -1;
  1031.         }
  1032.         ax_output(if_lookup(remote.ax->iface),
  1033.               remote.ax->ax25_addr,
  1034.               local.ax->ax25_addr,PID_NO_L3,bp);
  1035.         break;
  1036. #endif
  1037. #ifdef NETROM
  1038.     case TYPE_NETROML3:
  1039.         if(len_p(bp) > Nr_iface->mtu) {
  1040.             free_p(bp);
  1041.             errno = EMSGSIZE;
  1042.             return -1;
  1043.         }
  1044.         local.nr = (struct sockaddr_nr *)up->name;
  1045.         if(to != NULLCHAR)
  1046.             remote.nr = (struct sockaddr_nr *)to;
  1047.         else if(up->peername != NULLCHAR)
  1048.             remote.nr = (struct sockaddr_nr *)up->peername;
  1049.         else {
  1050.             errno = ENOTCONN;
  1051.             return -1;
  1052.         }
  1053.         /* The NETROM username is always ignored in outgoing traffic */
  1054.         nr_sendraw(remote.nr->nr_addr.node,
  1055.          up->cb.rnr->protocol,up->cb.rnr->protocol,bp);
  1056.         break;
  1057.     case TYPE_NETROML4:
  1058.         if((cb.nr4 = up->cb.nr4) == NULLNR4CB) {
  1059.             free_p(bp);
  1060.             errno = ENOTCONN;
  1061.             return -1;
  1062.         }
  1063.         if(len_p(bp) > Nr_iface->mtu){ /* reject big packets */
  1064.             free_p(bp);
  1065.             errno = EMSGSIZE;
  1066.             return -1;
  1067.         }
  1068.         send_nr4(cb.nr4,bp);
  1069.  
  1070.         while((cb.nr4 = up->cb.nr4) != NULLNR4CB &&
  1071.          cb.nr4->nbuffered >= cb.nr4->window){
  1072.             if(up->noblock){
  1073.                 errno = EWOULDBLOCK;
  1074.                 return -1;
  1075.             } else if((errno = (int)pwait(up)) != 0){
  1076.                 errno = EINTR;
  1077.                 return -1;
  1078.             }
  1079.         }
  1080.         if(cb.nr4 == NULLNR4CB){
  1081.             errno = EBADF;
  1082.             return -1;
  1083.         }
  1084.         break;
  1085. #endif
  1086.     }
  1087.     return cnt;
  1088. }
  1089. /* Return local name passed in an earlier bind() call */
  1090. int
  1091. getsockname(s,name,namelen)
  1092. int s;        /* Socket index */
  1093. char *name;    /* Place to stash name */
  1094. int *namelen;    /* Length of same */
  1095. {
  1096.     struct usock *up;
  1097.  
  1098.     if((up = itop(s)) == NULLUSOCK){
  1099.         errno = EBADF;
  1100.         return -1;
  1101.     }
  1102.     if(name == NULLCHAR || namelen == (int *)NULL){
  1103.         errno = EFAULT;
  1104.         return -1;
  1105.     }
  1106.     if(up->name == NULLCHAR){
  1107.         /* Not bound yet */
  1108.         *namelen = 0;
  1109.         return 0;
  1110.     }
  1111.     if(up->name != NULLCHAR){
  1112.         *namelen = (int)min(*namelen,up->namelen);
  1113.         memcpy(name,up->name,*namelen);
  1114.     }
  1115.     return 0;
  1116. }
  1117. /* Get remote name, returning result of earlier connect() call. */
  1118. int
  1119. getpeername(s,peername,peernamelen)
  1120. int s;            /* Socket index */
  1121. char *peername;        /* Place to stash name */
  1122. int *peernamelen;    /* Length of same */
  1123. {
  1124.     struct usock *up;
  1125.  
  1126.     if((up = itop(s)) == NULLUSOCK){
  1127.         errno = EBADF;
  1128.         return -1;
  1129.     }
  1130.     if(up->peername == NULLCHAR){
  1131.         errno = ENOTCONN;
  1132.         return -1;
  1133.     }
  1134.     if(peername == NULLCHAR || peernamelen == (int *)NULL){
  1135.         errno = EFAULT;
  1136.         return -1;
  1137.     }
  1138.     *peernamelen = (int)min(*peernamelen,up->peernamelen);
  1139.     memcpy(peername,up->peername,*peernamelen);
  1140.     return 0;
  1141. }
  1142. /* Return length of protocol queue, either send or receive. */
  1143. int
  1144. socklen(s,rtx)
  1145. int s;        /* Socket index */
  1146. int rtx;    /* 0 = receive queue, 1 = transmit queue */
  1147. {
  1148.     struct usock *up;
  1149.     int len = -1;
  1150.  
  1151.     if((up = itop(s)) == NULLUSOCK){
  1152.         errno = EBADF;
  1153.         return -1;
  1154.     }
  1155.     if(up->cb.p == NULLCHAR){
  1156.         errno = ENOTCONN;
  1157.         return -1;
  1158.     }
  1159.     if(rtx < 0 || rtx > 1){
  1160.         errno = EINVAL;
  1161.         return -1;
  1162.     }
  1163.     switch(up->type){
  1164.     case TYPE_LOCAL_DGRAM:
  1165.         switch(rtx){
  1166.         case 0:
  1167.             len = len_q(up->cb.local->q);
  1168.             break;
  1169.         case 1:
  1170.             if(up->cb.local->peer != NULLUSOCK)
  1171.                 len = len_q(up->cb.local->peer->cb.local->q);
  1172.             break;
  1173.         }
  1174.         break;
  1175.     case TYPE_LOCAL_STREAM:
  1176.         switch(rtx){
  1177.         case 0:
  1178.             len = len_p(up->cb.local->q) + len_p(up->ibuf);
  1179.             break;
  1180.         case 1:
  1181.             if(up->cb.local->peer != NULLUSOCK)
  1182.                 len = len_p(up->cb.local->peer->cb.local->q)
  1183.                       + len_p(up->obuf);
  1184.             break;
  1185.         }
  1186.         break;
  1187.     case TYPE_TCP:
  1188.         switch(rtx){
  1189.         case 0:
  1190.             len = up->cb.tcb->rcvcnt + len_p(up->ibuf);
  1191.             break;
  1192.         case 1:
  1193.             len = up->cb.tcb->sndcnt + len_p(up->obuf);
  1194.             break;
  1195.         }
  1196.         break;
  1197.     case TYPE_UDP:
  1198.         switch(rtx){
  1199.         case 0:
  1200.             len = up->cb.udp->rcvcnt;
  1201.             break;
  1202.         case 1:
  1203.             len = 0;
  1204.             break;
  1205.         }
  1206.         break;
  1207. #ifdef    AX25
  1208.     case TYPE_AX25I:
  1209.         switch(rtx){
  1210.         case 0:
  1211.             len = len_p(up->cb.ax25->rxq) + len_p(up->ibuf);
  1212.             break;
  1213.         case 1:    /* Number of bytes, not packets. DB3FL.910129 */
  1214.             len = len_p(up->cb.ax25->txq);
  1215.             if(up->obuf != NULLBUF)
  1216.                 len++;
  1217.         }
  1218.         break;
  1219.     case TYPE_AX25UI:
  1220.         switch(rtx){
  1221.         case 0:
  1222. /*
  1223.             len = len_q(Bcq);
  1224.             break;
  1225. */
  1226.         case 1:
  1227.             len = 0;
  1228.             break;
  1229.         }
  1230.         break;
  1231. #endif
  1232. #ifdef NETROM
  1233.     case TYPE_NETROML3:
  1234.         switch(rtx){
  1235.         case 0:
  1236.             len = len_q(up->cb.rnr->rcvq);
  1237.             break;
  1238.         case 1:
  1239.             len = 0;        
  1240.         }
  1241.         break;
  1242.     case TYPE_NETROML4:
  1243.         switch(rtx){
  1244.         case 0:
  1245.             len = len_p(up->cb.nr4->rxq) + len_p(up->obuf);
  1246.             break;
  1247.         case 1:    /* Number of bytes, not packets. DB3FL.900129 */
  1248.             len = len_p(up->cb.nr4->txq);
  1249.             if(up->obuf != NULLBUF)
  1250.                 len++;
  1251.             break;
  1252.         }
  1253.         break;
  1254. #endif
  1255.     case TYPE_RAW:
  1256.         switch(rtx){    
  1257.         case 0:
  1258.             len = len_q(up->cb.rip->rcvq);
  1259.             break;
  1260.         case 1:
  1261.             len = 0;        
  1262.             break;
  1263.         }
  1264.         break;
  1265.     }
  1266.     return len;
  1267. }
  1268. /* Force retransmission. Valid only for connection-oriented sockets. */
  1269. int
  1270. sockkick(s)
  1271. int s;    /* Socket index */
  1272. {
  1273.     struct usock *up;
  1274.  
  1275.     if((up = itop(s)) == NULLUSOCK){
  1276.         errno = EBADF;
  1277.         return -1;
  1278.     }
  1279.     if(up->type == TYPE_LOCAL_STREAM || up->type == TYPE_LOCAL_DGRAM){
  1280.         errno = EINVAL;
  1281.         return -1;
  1282.     }
  1283.     if(up->cb.p == NULLCHAR){
  1284.         errno = ENOTCONN;
  1285.         return -1;
  1286.     }
  1287.     switch(up->type){
  1288.     case TYPE_TCP:
  1289.         kick_tcp(up->cb.tcb);
  1290.         break;
  1291. #ifdef    AX25
  1292.     case TYPE_AX25I:
  1293.         kick_ax25(up->cb.ax25);
  1294.         break;
  1295. #endif
  1296. #ifdef NETROM
  1297.     case TYPE_NETROML4:
  1298.         kick_nr4(up->cb.nr4);
  1299.         break;
  1300. #endif
  1301.     default:
  1302.         /* Datagram sockets can't be kicked */
  1303.         errno = EOPNOTSUPP;
  1304.         return -1;
  1305.     }
  1306.     return 0;
  1307. }
  1308.  
  1309. /* Change owner of socket, return previous owner */
  1310. struct proc *
  1311. sockowner(s,newowner)
  1312. int s;                        /* Socket index */
  1313. struct proc *newowner;        /* Process table address of new owner */
  1314. {
  1315.     struct usock *up;
  1316.     struct proc *pp;
  1317.  
  1318.     if((up = itop(s)) == NULLUSOCK){
  1319.         errno = EBADF;
  1320.         return NULLPROC;
  1321.     }
  1322.     pp = up->owner;
  1323.  
  1324.     if(newowner != NULLPROC)
  1325.         up->owner = newowner;
  1326.  
  1327.     return pp;
  1328. }
  1329.  
  1330. /* Close down a socket three ways. Type 0 means "no more receives"; this
  1331.  * replaces the incoming data upcall with a routine that discards further
  1332.  * data. Type 1 means "no more sends", and obviously corresponds to sending
  1333.  * a TCP FIN. Type 2 means "no more receives or sends". This I interpret
  1334.  * as "abort the connection".
  1335.  */
  1336. int
  1337. shutdown(s,how)
  1338. int s;        /* Socket index */
  1339. int how;    /* (see above) */
  1340. {
  1341.     struct usock *up;
  1342.  
  1343.     if((up = itop(s)) == NULLUSOCK){
  1344.         errno = EBADF;
  1345.         return -1;
  1346.     }
  1347.     if(up->cb.p == NULLCHAR){
  1348.         errno = ENOTCONN;
  1349.         return -1;
  1350.     }
  1351.     switch(up->type){
  1352.     case TYPE_LOCAL_DGRAM:
  1353.     case TYPE_LOCAL_STREAM:
  1354.         if(up->cb.local->q == NULLBUF)
  1355.             close_s(s);
  1356.         else
  1357.             up->cb.local->flags = LOC_SHUTDOWN;
  1358.         break;
  1359.     case TYPE_TCP:
  1360.         switch(how){
  1361.         case 0:    /* No more receives -- replace upcall */
  1362.             up->cb.tcb->r_upcall = trdiscard;
  1363.             break;
  1364.         case 1:    /* Send EOF */
  1365.             close_tcp(up->cb.tcb);
  1366.             break;
  1367.         case 2:    /* Blow away TCB */
  1368.             reset_tcp(up->cb.tcb);
  1369.             up->cb.tcb = NULLTCB;
  1370.             break;
  1371.         }
  1372.         break;
  1373. #ifdef    AX25
  1374.     case TYPE_AX25UI:
  1375.         close_s(s);
  1376.         break;
  1377.     case TYPE_AX25I:
  1378.         switch(how){
  1379.         case 0:
  1380.         case 1:    /* Attempt regular disconnect */
  1381.             disc_ax25(up->cb.ax25);
  1382.             break;
  1383.         case 2: /* Blow it away */
  1384.             reset_ax25(up->cb.ax25);
  1385.             up->cb.ax25 = NULLAX25;
  1386.             break;
  1387.         }
  1388.         break;
  1389. #endif
  1390. #ifdef    NETROM
  1391.     case TYPE_NETROML3:
  1392.         close_s(s);
  1393.         break;
  1394.     case TYPE_NETROML4:
  1395.         switch(how){
  1396.         case 0:
  1397.         case 1:    /* Attempt regular disconnect */
  1398.             disc_nr4(up->cb.nr4);
  1399.             break;
  1400.         case 2: /* Blow it away */
  1401.             reset_nr4(up->cb.nr4);
  1402.             up->cb.nr4 = NULLNR4CB;
  1403.             break;
  1404.         }
  1405.         break;
  1406. #endif
  1407.     case TYPE_RAW:
  1408.     case TYPE_UDP:
  1409.         close_s(s);
  1410.         break;
  1411.     default:
  1412.         errno = EOPNOTSUPP;
  1413.         return -1;
  1414.     }
  1415.     psignal(up,0);
  1416.     return 0;
  1417. }
  1418. /* Close a socket, freeing it for reuse. Try to do a graceful close on a
  1419.  * TCP socket, if possible
  1420.  */
  1421. int
  1422. close_s(s)
  1423. int s;        /* Socket index */
  1424. {
  1425.     struct usock *up;
  1426.     if((up = itop(s)) == NULLUSOCK){
  1427.         errno = EBADF;
  1428.         return -1;
  1429.     }
  1430.     if(--up->refcnt > 0)
  1431.         return 0;    /* Others are still using it */
  1432.     usflush(s);
  1433.     if(up->ibuf != NULLBUF){
  1434.         free_p(up->ibuf);
  1435.         up->ibuf = NULLBUF;
  1436.     }
  1437.     switch(up->type){
  1438.     case TYPE_LOCAL_STREAM:
  1439.     case TYPE_LOCAL_DGRAM:
  1440.         if(up->cb.local->peer != NULLUSOCK){
  1441.             up->cb.local->peer->cb.local->peer = NULLUSOCK;
  1442.             psignal(up->cb.local->peer,0);
  1443.         }
  1444.         free_q(&up->cb.local->q);
  1445.         xfree(up->cb.local);
  1446.         break;
  1447.     case TYPE_TCP:
  1448.         if(up->cb.tcb != NULLTCB){    /* In case it's been reset */
  1449.             up->cb.tcb->r_upcall = trdiscard;
  1450.             /* Tell the TCP_CLOSED upcall there's no more socket */
  1451.             up->cb.tcb->user = -1;
  1452.             close_tcp(up->cb.tcb);
  1453.         }
  1454.         break;
  1455.     case TYPE_UDP:
  1456.         if(up->cb.udp != NULLUDP){
  1457.             del_udp(up->cb.udp);
  1458.         }
  1459.         break;
  1460. #ifdef    AX25
  1461.     case TYPE_AX25I:
  1462.         if(up->cb.ax25 != NULLAX25){
  1463.             /* Tell the TCP_CLOSED upcall there's no more socket */
  1464.             up->cb.ax25->user = -1;
  1465.             disc_ax25(up->cb.ax25);
  1466.         }
  1467.         break;
  1468.     case TYPE_AX25UI:
  1469.         Axui_sock = -1;
  1470. /*
  1471.         free_q(&Bcq);
  1472.         psignal(&Bcq,0);    /* Unblock any reads */
  1473.         break;
  1474. #endif
  1475. #ifdef    NETROM
  1476.     case TYPE_NETROML3:
  1477.         del_rnr(up->cb.rnr);
  1478.         break;
  1479.     case TYPE_NETROML4:
  1480.         if(up->cb.nr4 != NULLNR4CB){
  1481.             /* Tell the TCP_CLOSED upcall there's no more socket */
  1482.             up->cb.nr4->user = -1;
  1483.             disc_nr4(up->cb.nr4);
  1484.         }
  1485.         break;
  1486.  
  1487. #endif
  1488.     case TYPE_RAW:
  1489.         del_ip(up->cb.rip);
  1490.         break;
  1491.     default:
  1492.         errno = EOPNOTSUPP;
  1493.         return -1;
  1494.     }
  1495. #ifdef    LZW
  1496.     if(up->zout != NULLLZW || up->zin != NULLLZW)
  1497.         lzwfree(up);
  1498. #endif
  1499.     xfree(up->name);
  1500.     xfree(up->peername);
  1501.     up->cb.p = NULLCHAR;
  1502.     up->name = up->peername = NULLCHAR;
  1503.     up->type = NOTUSED;
  1504.     psignal(up,0);    /* Wake up anybody doing an accept() or recv() */
  1505.     return 0;
  1506. }
  1507.  
  1508. /* Increment reference count for specified socket */
  1509. int
  1510. usesock(int s)
  1511. {
  1512.     struct usock *up;
  1513.  
  1514.     if((up = itop(s)) == NULLUSOCK){
  1515.         errno = EBADF;
  1516.         return -1;
  1517.     }
  1518.     up->refcnt++;
  1519.     return 0;
  1520. }
  1521.  
  1522. /* Blow away all sockets belonging to a certain process. Used by killproc(). */
  1523. void
  1524. freesock(struct proc *pp)
  1525. {
  1526.     struct usock *up;
  1527.     int i;
  1528.     for(i = SOCKBASE; i < (Nusock + SOCKBASE); i++)
  1529.         if((up = itop(i)) != NULLUSOCK)
  1530.             if(up->type != NOTUSED && up->owner == pp)
  1531.                 shutdown(i,2);
  1532. }
  1533.  
  1534. /* Start of internal subroutines */
  1535.  
  1536. /* Raw IP receive upcall routine */
  1537. static void
  1538. rip_recv(rp)
  1539. struct raw_ip *rp;
  1540. {
  1541.     psignal(itop(rp->user),1);
  1542.     pwait(NULL);
  1543. }
  1544.  
  1545. /* UDP receive upcall routine */
  1546. static void
  1547. s_urcall(iface,udp,cnt)
  1548. struct iface *iface;
  1549. struct udp_cb *udp;
  1550. int cnt;
  1551. {
  1552.     psignal(itop(udp->user),1);
  1553.     pwait(NULL);
  1554. }
  1555.  
  1556. /* TCP receive upcall routine */
  1557. static void
  1558. s_trcall(tcb,cnt)
  1559. struct tcb *tcb;
  1560. int cnt;
  1561. {
  1562.     /* Wake up anybody waiting for data, and let them run */
  1563.     psignal(itop(tcb->user),1);
  1564.     pwait(NULL);
  1565. }
  1566. /* TCP transmit upcall routine */
  1567. static void
  1568. s_ttcall(tcb,cnt)
  1569. struct tcb *tcb;
  1570. int cnt;
  1571. {
  1572.     /* Wake up anybody waiting to send data, and let them run */
  1573.     psignal(itop(tcb->user),1);
  1574.     pwait(NULL);
  1575. }
  1576. /* TCP state change upcall routine */
  1577. static void
  1578. s_tscall(tcb,old,new)
  1579. struct tcb *tcb;
  1580. int old,new;
  1581. {
  1582.     int s = tcb->user, ns;
  1583.     union sp sp;
  1584.     struct usock *nup, *oup, *up = itop(s);
  1585.  
  1586.     oup = up;
  1587.  
  1588.     switch(new){
  1589.     case TCP_CLOSED:
  1590.         /* Clean up. If the user has already closed the socket,
  1591.          * then up will be null (s was set to -1 by the close routine).
  1592.          * If not, then this is an abnormal close (e.g., a reset)
  1593.          * and clearing out the pointer in the socket structure will
  1594.          * prevent any further operations on what will be a freed
  1595.          * control block. Also wake up anybody waiting on events
  1596.          * related to this tcb so they will notice it disappearing.
  1597.          */
  1598.         if(up != NULLUSOCK){
  1599.             up->cb.tcb = NULLTCB;
  1600.             up->errcodes[0] = tcb->reason;
  1601.             up->errcodes[1] = tcb->type;
  1602.             up->errcodes[2] = tcb->code;
  1603.         }
  1604.         del_tcp(tcb);
  1605.         break;
  1606.     case TCP_SYN_RECEIVED:
  1607.         /* Handle an incoming connection. If this is a server TCB,
  1608.          * then we're being handed a "clone" TCB and we need to
  1609.          * create a new socket structure for it. In either case,
  1610.          * find out who we're talking to and wake up the guy waiting
  1611.          * for the connection.
  1612.          */
  1613.         if(tcb->flags.clone){
  1614.             /* Clone the socket */
  1615.             ns = socket(AF_INET,SOCK_STREAM,0);
  1616.             nup = itop(ns);
  1617.             ASSIGN(*nup,*up);
  1618.             tcb->user = ns;
  1619.             nup->cb.tcb = tcb;
  1620.             /* Allocate new memory for the name areas */
  1621.             nup->name = mxallocw(SOCKSIZE);
  1622.             nup->peername = mxallocw(SOCKSIZE);
  1623.             /* Store the new socket # in the old one */
  1624.             up->rdysock = ns;
  1625.             up = nup;
  1626.             s = ns;
  1627.         } else {
  1628.             /* Allocate space for the peer's name */
  1629.             up->peername = mxallocw(SOCKSIZE);
  1630.             /* Store the old socket # in the old socket */
  1631.             up->rdysock = s;
  1632.         }
  1633.         /* Load the addresses. Memory for the name has already
  1634.          * been allocated, either above or in the original bind.
  1635.          */
  1636.         sp.p = up->name;
  1637.         sp.in->sin_family = AF_INET;
  1638.         sp.in->sin_addr.s_addr = up->cb.tcb->conn.local.address;
  1639.         sp.in->sin_port = up->cb.tcb->conn.local.port;
  1640.         up->namelen = SOCKSIZE;
  1641.  
  1642.         sp.p = up->peername;
  1643.         sp.in->sin_family = AF_INET;
  1644.         sp.in->sin_addr.s_addr = up->cb.tcb->conn.remote.address;
  1645.         sp.in->sin_port = up->cb.tcb->conn.remote.port;
  1646.         up->peernamelen = SOCKSIZE;
  1647.  
  1648.         /* Wake up the guy accepting it, and let him run */
  1649.         psignal(oup,1);
  1650.     
  1651.     pwait(NULL);
  1652.         break;
  1653.     default:    /* Ignore all other state transitions */
  1654.         break;
  1655.     }
  1656.     psignal(up,0);    /* In case anybody's waiting */
  1657. }
  1658. /* Discard data received on a TCP connection. Used after a receive shutdown or
  1659.  * close_s until the TCB disappears.
  1660.  */
  1661. static void
  1662. trdiscard(tcb,cnt)
  1663. struct tcb *tcb;
  1664. int cnt;
  1665. {
  1666.     struct mbuf *bp;
  1667.  
  1668.     recv_tcp(tcb,&bp,(int16)cnt);
  1669.     free_p(bp);
  1670. }
  1671. /*
  1672. #ifdef    AX25        DB3FL
  1673. */
  1674. /* AX.25 receive upcall */
  1675. void
  1676. s_arcall(axp,cnt)
  1677. struct ax25_cb *axp;
  1678. int cnt;
  1679. {
  1680.     int ns;
  1681.     union sp sp;
  1682.     struct usock *nup, *oup, *up = itop(axp->user);
  1683.     /* When AX.25 data arrives for the first time the AX.25 listener
  1684.        is notified, if active. If the AX.25 listener is a server its
  1685.        socket is duplicated in the same manner as in s_tscall().
  1686.      */
  1687.  
  1688.     if (Axi_sock != -1 && axp->user == -1) {
  1689.         oup = up = itop(Axi_sock);
  1690.         /* From now on, use the same upcalls as the listener */
  1691.         axp->t_upcall = up->cb.ax25->t_upcall;
  1692.         axp->r_upcall = up->cb.ax25->r_upcall;
  1693.         axp->s_upcall = up->cb.ax25->s_upcall;
  1694.         if (up->cb.ax25->clone) {
  1695.             /* Clone the socket */
  1696.             ns = socket(AF_AX25,SOCK_STREAM,0);
  1697.             nup = itop(ns);
  1698.             ASSIGN(*nup,*up);
  1699.             axp->user = ns;
  1700.             nup->cb.ax25 = axp;
  1701.             /* Allocate new memory for the name areas */
  1702.             nup->name = mxallocw(sizeof(struct sockaddr_ax));
  1703.             nup->peername = mxallocw(sizeof(struct sockaddr_ax));
  1704.             /* Store the new socket # in the old one */
  1705.             up->rdysock = ns;
  1706.             up = nup;
  1707.         } else {
  1708.             axp->user = Axi_sock;
  1709.             del_ax25(up->cb.ax25);
  1710.             up->cb.ax25 = axp;
  1711.             /* Allocate space for the peer's name */
  1712.             up->peername = mxallocw(sizeof(struct sockaddr_ax));
  1713.             /* Store the old socket # in the old socket */
  1714.             up->rdysock = Axi_sock;
  1715.         }
  1716.         /* Load the addresses. Memory for the name has already
  1717.          * been allocated, either above or in the original bind.
  1718.          */
  1719.         sp.p = up->name;
  1720.         sp.ax->sax_family = AF_AX25;
  1721.         memcpy(sp.ax->ax25_addr,axp->path + AXALEN,AXALEN);
  1722.         memcpy(sp.ax->iface,axp->iface->name,ILEN);
  1723.         up->namelen = sizeof(struct sockaddr_ax);
  1724.  
  1725.         sp.p = up->peername;
  1726.         sp.ax->sax_family = AF_AX25;
  1727.         memcpy(sp.ax->ax25_addr,axp->path,AXALEN);
  1728.         memcpy(sp.ax->iface,axp->iface->name,ILEN);
  1729.         up->peernamelen = sizeof(struct sockaddr_ax);
  1730.         /* Wake up the guy accepting it, and let him run */
  1731.         psignal(oup,1);
  1732.         pwait(NULL);
  1733.         return;
  1734.     }
  1735.     /* Wake up anyone waiting, and let them run */
  1736.     psignal(up,1);
  1737.     pwait(NULL);
  1738. }
  1739. /* AX.25 transmit upcall */
  1740. void
  1741. s_atcall(axp,cnt)
  1742. struct ax25_cb *axp;
  1743. int cnt;
  1744. {
  1745.     /* Wake up anyone waiting, and let them run */
  1746.     psignal(itop(axp->user),1);
  1747.     pwait(NULL);
  1748. }
  1749. /* AX25 state change upcall routine */
  1750. void
  1751. s_ascall(axp,old,new)
  1752. register struct ax25_cb *axp;
  1753. int old,new;
  1754. {
  1755.     struct usock *up = itop(axp->user);
  1756.     switch(new){
  1757.     case DISCONNECTED:
  1758.         /* Clean up. If the user has already closed the socket,
  1759.          * then up will be null (s was set to -1 by the close routine).
  1760.          * If not, then this is an abnormal close (e.g., a reset)
  1761.          * and clearing out the pointer in the socket structure will
  1762.          * prevent any further operations on what will be a freed
  1763.          * control block. Also wake up anybody waiting on events
  1764.          * related to this block so they will notice it disappearing.
  1765.          */
  1766.         if(up != NULLUSOCK){
  1767.             up->errcodes[0] = axp->reason;
  1768.             up->cb.ax25 = NULLAX25;
  1769.         }
  1770.         del_ax25(axp);
  1771.     default:    /* Other transitions are ignored */
  1772.         break;
  1773.     }
  1774.     psignal(up,0);    /* In case anybody's waiting */
  1775. }
  1776. /*
  1777. #endif
  1778. */
  1779. #ifdef NETROM
  1780. /* NET/ROM receive upcall routine */
  1781. static void
  1782. s_nrcall(cb,cnt)
  1783. struct nr4cb *cb;
  1784. int cnt;
  1785. {
  1786.     /* Wake up anybody waiting for data, and let them run */
  1787.     psignal(itop(cb->user),1);
  1788.     pwait(NULL);
  1789. }
  1790. /* NET/ROM transmit upcall routine */
  1791. static void
  1792. s_ntcall(cb,cnt)
  1793. struct nr4cb *cb;
  1794. int cnt;
  1795. {
  1796.     /* Wake up anybody waiting to send data, and let them run */
  1797.     psignal(itop(cb->user),1);
  1798.     pwait(NULL);
  1799. }
  1800. /* NET/ROM state change upcall routine */
  1801. static void
  1802. s_nscall(cb,old,new)
  1803. struct nr4cb *cb;
  1804. int old,new;
  1805. {
  1806.     int s = cb->user, ns;
  1807.     struct usock *oup, *nup, *up = itop(s);
  1808.     union sp sp;
  1809.  
  1810.     oup = up;
  1811.  
  1812.      if(new == NR4STDISC && up != NULLUSOCK){
  1813.         /* Clean up. If the user has already closed the socket,
  1814.          * then up will be null (s was set to -1 by the close routine).
  1815.          * If not, then this is an abnormal close (e.g., a reset)
  1816.          * and clearing out the pointer in the socket structure will
  1817.          * prevent any further operations on what will be a freed
  1818.          * control block. Also wake up anybody waiting on events
  1819.          * related to this cb so they will notice it disappearing.
  1820.          */
  1821.          up->cb.nr4 = NULLNR4CB;
  1822.          up->errcodes[0] = cb->dreason;
  1823.      }
  1824.      if(new == NR4STCON && old == NR4STDISC){
  1825.         /* Handle an incoming connection. If this is a server cb,
  1826.          * then we're being handed a "clone" cb and we need to
  1827.          * create a new socket structure for it. In either case,
  1828.          * find out who we're talking to and wake up the guy waiting
  1829.          * for the connection.
  1830.          */
  1831.         if(cb->clone){
  1832.             /* Clone the socket */
  1833.             ns = socket(AF_NETROM,SOCK_SEQPACKET,0);
  1834.             nup = itop(ns);
  1835.             ASSIGN(*nup,*up);
  1836.             cb->user = ns;
  1837.             nup->cb.nr4 = cb;
  1838.             cb->clone = 0; /* to avoid getting here again */
  1839.             /* Allocate new memory for the name areas */
  1840.             nup->name = mxallocw(sizeof(struct sockaddr_nr));
  1841.             nup->peername = mxallocw(sizeof(struct sockaddr_nr));
  1842.             /* Store the new socket # in the old one */
  1843.             up->rdysock = ns;
  1844.             up = nup;
  1845.             s = ns;
  1846.         } else {
  1847.             /* Allocate space for the peer's name */
  1848.             up->peername = mxallocw(sizeof(struct sockaddr_nr));
  1849.             /* Store the old socket # in the old socket */
  1850.             up->rdysock = s;
  1851.         }
  1852.         /* Load the addresses. Memory for the name has already
  1853.          * been allocated, either above or in the original bind.
  1854.          */
  1855.         sp.p = up->name;
  1856.         sp.nr->nr_family = AF_NETROM;
  1857.         ASSIGN(sp.nr->nr_addr,up->cb.nr4->local);
  1858.         up->namelen = sizeof(struct sockaddr_nr);
  1859.  
  1860.         sp.p = up->peername;
  1861.         sp.nr->nr_family = AF_NETROM;
  1862.         ASSIGN(sp.nr->nr_addr,up->cb.nr4->remote);
  1863.         up->peernamelen = sizeof(struct sockaddr_nr);
  1864.  
  1865.         /* Wake up the guy accepting it, and let him run */
  1866.         psignal(oup,1);
  1867.         pwait(NULL);
  1868.     }
  1869.      /* Ignore all other state transitions */    
  1870.     psignal(up,0);    /* In case anybody's waiting */
  1871. }
  1872. #endif
  1873.  
  1874. /* Verify address family and length according to the socket type */
  1875. static int near
  1876. checkaddr(type,name,namelen)
  1877. int type;
  1878. char *name;
  1879. int namelen;
  1880. {
  1881.     struct sockaddr *sp = (struct sockaddr *)name;
  1882.  
  1883.     /* Verify length and address family according to protocol */
  1884.     switch(type){
  1885.     case TYPE_TCP:
  1886.     case TYPE_UDP:
  1887.         if(sp->sa_family != AF_INET || namelen != sizeof(struct sockaddr_in))
  1888.             return -1;
  1889.         break;
  1890. #ifdef    AX25
  1891.     case TYPE_AX25I:
  1892.     case TYPE_AX25UI:
  1893.         if(sp->sa_family != AF_AX25
  1894.          || namelen != sizeof(struct sockaddr_ax))
  1895.             return -1;
  1896.         break;
  1897. #endif
  1898. #ifdef    NETROM
  1899.     case TYPE_NETROML3:
  1900.     case TYPE_NETROML4:
  1901.         if(sp->sa_family != AF_NETROM
  1902.          || namelen != sizeof(struct sockaddr_nr))
  1903.             return -1;
  1904.         break;
  1905. #endif
  1906.     }
  1907.     return 0;
  1908. }
  1909. /* Issue an automatic bind of a local address */
  1910. static void near
  1911. autobind(s,af)
  1912. int s,af;
  1913. {
  1914.     char buf[MAXSOCKSIZE];
  1915.     union sp sp;
  1916.  
  1917.     sp.p = buf;
  1918.  
  1919.     switch(af){
  1920.     case AF_INET:
  1921.         sp.in->sin_family = AF_INET;
  1922.         sp.in->sin_addr.s_addr = INADDR_ANY;
  1923.         sp.in->sin_port = Lport++;
  1924.         bind(s,sp.p,sizeof(struct sockaddr_in));
  1925.         break;
  1926. #ifdef    AX25
  1927.     case AF_AX25:
  1928.         sp.ax->sax_family = AF_AX25;
  1929.         memset(sp.ax->ax25_addr,'\0',AXALEN);
  1930.         memset(sp.ax->iface,'\0',ILEN);
  1931.         bind(s,sp.p,sizeof(struct sockaddr_ax));
  1932.         break;
  1933. #endif
  1934. #ifdef    NETROM
  1935.     case AF_NETROM:
  1936.         sp.nr->nr_family = AF_NETROM;
  1937.         memcpy(sp.nr->nr_addr.user,Mycall,AXALEN);
  1938.         memcpy(sp.nr->nr_addr.node,Mycall,AXALEN);
  1939.         bind(s,sp.p,sizeof(struct sockaddr_nr));
  1940.         break;
  1941. #endif
  1942.     }
  1943. }
  1944.  
  1945. #ifdef XXX
  1946. /* Return a pair of mutually connected sockets in sv[0] and sv[1] */
  1947. int
  1948. socketpair(af,type,protocol,sv)
  1949. int af;
  1950. int type;
  1951. int protocol;
  1952. int sv[];
  1953. {
  1954.     struct usock *up0, *up1;
  1955.  
  1956.     if(sv == NULLINT){
  1957.         errno = EFAULT;
  1958.         return -1;
  1959.     }
  1960.     if(af != AF_LOCAL){
  1961.         errno = EAFNOSUPPORT;
  1962.         return -1;
  1963.     }
  1964.     if(type != SOCK_STREAM && type != SOCK_DGRAM){
  1965.         errno = ESOCKTNOSUPPORT;
  1966.         return -1;
  1967.     }
  1968.     if((sv[0] = socket(af,type,protocol)) == -1)
  1969.         return -1;
  1970.     if((sv[1] = socket(af,type,protocol)) == -1){
  1971.         close_s(sv[0]);
  1972.         return -1;
  1973.     }
  1974.     up0 = itop(sv[0]);
  1975.     up1 = itop(sv[1]);
  1976.     up0->cb.local->peer = up1;
  1977.     up1->cb.local->peer = up0;
  1978.     return sv[1];
  1979. }
  1980. #endif
  1981.  
  1982.